package com.zytech.zspider.transformer;

import com.google.common.base.Charsets;
import com.zytech.modules.lang.IOs;
import com.zytech.modules.lang.Langs;
import com.zytech.modules.lang.Requires;
import com.zytech.zspider.core.SpiderDefinition;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author siuming
 */
class DefaultSpiderDefinitionTransformer implements SpiderDefinitionTransformer {

    @Override
    public SpiderDefinition transform(InputStream in) {
        Requires.notNull(in, "in must not be null.");
        try {

            ByteArrayOutputStream out = new ByteArrayOutputStream();
            IOs.piping(in, out);
            return transform(new String(out.toByteArray(), Charsets.UTF_8));
        } catch (IOException e) {
            throw Langs.toUncheck(e);
        }
    }

    @Override
    public SpiderDefinition transform(String text) {
        Requires.hasText(text, "text must not be null or empty.");

        ParseTree parseTree = constructParseTree(text);
        ParseTreeWalker parseTreeWalker = new ParseTreeWalker();
        SpiderDefinitionTransformerListener listener = new SpiderDefinitionTransformerListener();
        parseTreeWalker.walk(listener, parseTree);
        return listener.getDef();
    }

    private ParseTree constructParseTree(String text) {
        ANTLRErrorListener errorListener = new SpiderDefinitionTransformerErrorListener();
        CharStream charStream = new ANTLRInputStream(text);
        SpiderDefinitionLexer lexer = new SpiderDefinitionLexer(charStream);
        lexer.addErrorListener(errorListener);
        TokenStream tokenStream = new CommonTokenStream(lexer);
        SpiderDefinitionParser parser = new SpiderDefinitionParser(tokenStream);
        parser.addErrorListener(errorListener);
        return parser.transform();
    }
}
